﻿using habbo.Kernel.Network;
using habbo.Kernel.Storage.Querys;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace habbo.Habbo.Characters
{
    class CharacterManager
    {
        /// <summary>
        /// Cache for offline users.
        /// </summary>
        public Dictionary<int, Character> WeakSQLCache { get; private set; }

        public CharacterManager()
        {
            WeakSQLCache = new Dictionary<int, Character>();
        }

        /// <summary>
        /// Returns the status of an character.
        /// </summary>
        /// <param name="Username"></param>
        /// <returns></returns>
        public CharacterStatus GetStatus(string Username, out Session Session)
        {
            Session = SystemApp.SocketSystem.GetSession(Username);

            return Session != null ? CharacterStatus.Online : CharacterStatus.Offline;
        }

        /// <summary>
        /// Returns the status of an character.
        /// </summary>
        /// <param name="Username"></param>
        /// <returns></returns>
        public CharacterStatus GetStatus(int Id, out Session Session)
        {
            Session = SystemApp.SocketSystem.GetSession(Id);

            return Session != null ? CharacterStatus.Online : CharacterStatus.Offline;
        }

        /// <summary>
        /// Returns an figure, cache or sql.
        /// </summary>
        /// <param name="CharacterId"></param>
        /// <returns></returns>
        public string GetFigure(int CharacterId)
        {
            Session Session;

            if (GetStatus(CharacterId, out Session) == CharacterStatus.Online)
            {
                return Session.Character.Figure;
            }

            Character Character;

            if (GetCharacter(CharacterId, out Character))
            {
                return Character.Figure;
            }

            return string.Empty;
        }

        /// <summary>
        /// Returns an motto, cache or sql.
        /// </summary>
        /// <param name="CharacterId"></param>
        /// <returns></returns>
        public string GetMotto(int CharacterId)
        {
            Session Session;

            if (GetStatus(CharacterId, out Session) == CharacterStatus.Online)
            {
                return Session.Character.Motto;
            }

            return string.Empty;
        }

        /// <summary>
        /// Returns an motto, cache or sql.
        /// </summary>
        /// <param name="CharacterId"></param>
        /// <returns></returns>
        public string GetRealName(int CharacterId)
        {
            Session Session;

            if (GetStatus(CharacterId, out Session) == CharacterStatus.Online)
            {
                return Session.Character.RealName;
            }

            return string.Empty;
        }

        public string GetUsername(int CharacterId)
        {
            Character Character;

            if (GetCharacter(CharacterId, out Character))
            {
                return Character.Username;
            }

            return "Unknown character.";
        }

        public bool GetCharacter(int CharacterId, out Character Character)
        {
            Character = null;

            foreach (Character xCharacter in WeakSQLCache.Values)
            {
                if (xCharacter.Id == CharacterId)
                {
                    Character = xCharacter;
                }
            }

            if (Character != null)
            {
                return true;
            }
            else
            {
                DataRow Obj = SystemApp.MySQLManager.GetObject(new CastCharacterQuery(CharacterId)).GetOutput<DataRow>();

                if (Obj != null)
                {
                    Character = new Character(Obj);
                    WeakSQLCache.Add(Character.Id, Character);
                }

                return Character != null;
            }
        }

        public bool GetCharacter(string Username, out Character Character)
        {
            Character = null;

            foreach (Character xCharacter in WeakSQLCache.Values)
            {
                if (xCharacter.Username.ToLower() == Username.ToLower())
                {
                    Character = xCharacter;
                }
            }

            if (Character != null)
            {
                return true;
            }
            else
            {
                DataRow Obj = SystemApp.MySQLManager.GetObject(new CastCharacterQuery(Username)).GetOutput<DataRow>();

                if (Obj != null)
                {
                    Character = new Character(Obj);
                    WeakSQLCache.Add(Character.Id, Character);
                }

                return Character != null;
            }
        }

        public Character Authenticate(string AuthTicket)
        {
            DataRow Obj = SystemApp.MySQLManager.GetObject(new CharacterTicketQuery(AuthTicket)).GetOutput<DataRow>();

            if (Obj != null)
            {
                return new Character(Obj);
            }

            return null;
        }

        /// <summary>
        /// Returns the status of an character.
        /// </summary>
        /// <param name="CharacterId"></param>
        /// <returns></returns>
        public CharacterStatus GetStatus(int CharacterId)
        {
            return SystemApp.SocketSystem.GetSession(CharacterId) != null ? CharacterStatus.Online : CharacterStatus.Offline;
        }

        /// <summary>
        /// Returns the status of an character.
        /// </summary>
        /// <param name="Username"></param>
        /// <returns></returns>
        public CharacterStatus GetStatus(string Username)
        {
            return SystemApp.SocketSystem.GetSession(Username) != null ? CharacterStatus.Online : CharacterStatus.Offline;
        }
    }

    enum CharacterStatus
    {
        Online, Offline
    }
}
